/**
 * @description 接口监测
*/

import { apiMonitor, errorMonitor, performanceMonitor } from '@daelui/dogjs/dist/components'
import dog from '@daelui/dogjs'
import '../public/config/app.config.js'
import interSer from './service/action/collect-inter.action.js'
import errorSer from './service/action/collect-error.action.js'
import perSer from './service/action/collect-performance.action.js'

// 全局定义
var $dog = window.$dog
if ($dog) {
  for (let key in $dog) {
    dog[key] = $dog[key]
  }
}
window.$dog = $dog = dog

/* API */
/**
 * @function 是否存储
*/
apiMonitor.isStoreAble = function (req) {
  req = req || {}
  // 无效数据
  if (!req.url || !/post|get|put|delete/i.test(req.method)) {
    return false
  }
  // 排除接口
  else if (/collect\/(inter|group|error|performance|ube|store|list|url|item)/i.test(req.url)) {
    return false
  }
  // 排除无状态的接口
  else if (!/^\d+$/i.test(req.status)) {
    return false
  }
  return true
}

/**
 * @function 存储数据
*/
apiMonitor.store = function (data) {
  interSer.store(data)
}

/* ERROR */
/**
 * @function 是否存储
*/
errorMonitor.isStoreAble = function (req) {
  req = req || {}
  return true
}

/**
 * @function 存储数据
*/
errorMonitor.store = function (data) {
  errorSer.store(data)
}

/* Performance */
/**
 * @function 存储数据
*/
performanceMonitor.store = function (data) {
  perSer.store(data)
}

/* ERROR */
/**
 * @function 是否存储
*/
performanceMonitor.isStoreAble = function (req) {
  req = req || {}
  return true
}

// 代理规则
let proxiers = window.$dog?.proxiers
proxiers = Array.isArray(proxiers) ? proxiers : []

/**
 * @function 是否匹配规则
 * @param serviceType ajax/fetch/script
 * @param cat open/send/reqHeaders/responseText
*/
function transformByRules (options, serviceType, cat) {
  proxiers.forEach(pro => {
    // 要求匹配参数
    if (String(pro.isMatchParams) === 'true' || String(pro.isMatchParams) === '1') {
      // 无匹配项则不再执行
      if (!isMatchParams(pro)) {
        return options
      }
    }
    // 是否与服务类型匹配
    if (String(pro.serviceType || '--').indexOf(serviceType || '**') === -1) {
      return options
    }
    if (String(pro.isBeforeDebugger) === 'true') {
      debugger
    }
    // 规则匹配
    let matchRules = pro.matchRules
    let ruleMap = new Map()
    matchRules = Array.isArray(matchRules) ? matchRules : []
    let isMatch = false, isAndMatch = true, orModes = []
    matchRules.forEach(rule => {
      const matchItem = rule.matchItem
      // 进行规则判断的值
      let values = []
      // 打开
      if (/open/.test(cat) && /url|method|async/.test(matchItem)) {
        values = [options[rule.matchItem]]
      }
      // 发送
      else if (/send/.test(cat) && /request/.test(matchItem)) {
        let payload = options.requestPayload || ''
        let query = options.requestQuery || ''
        if (typeof options.requestPayload === 'object') {
          try {
            payload = JSON.stringify(options.requestPayload)
          } catch (e) {
            payload = ''
          }
        }
        values = [payload, query]
      }
      // 请求头
      else if (/reqHeaders/.test(cat) && /reqHeaderKey|reqHeaderValue/.test(matchItem)) {
        let reqHeaders = options.reqHeaders || {}
        let keys = Object.keys(reqHeaders)
        // 头key
        if (matchItem === 'reqHeaderKey') {
          values = keys
        }
        // 头值
        else if (matchItem === 'reqHeaderValue') {
          values = keys.map(key => {
            return reqHeaders[key]
          })
        }
      }
      // 规则值类型
      let typer = Object.prototype.toString.call(rule.match)
      let b = false
      // 值与规则判断
      values.forEach(value => {
        if (value === '' || value === null || value === undefined) {
          return true
        }
        // 字符串
        if (typer === '[object String]' || typer === '[object Number]') {
          b = String(value).indexOf(rule.match) > -1
        }
        // 正则
        else if (typer === '[object RegExp]') {
          b = rule.match.test(value)
        }
        // 函数
        else if (typer === '[object Function]') {
          try {
            b = rule.match(value, options, rule)
          } catch (e) {
            b = false
          }
        }
      })
      ruleMap.set(rule.id, b)
      if (rule.matchMode === 'and') {
        isAndMatch = b && isAndMatch
      } else {
        isMatch = b || isMatch
        orModes.push(1)
      }
    })
    // 全部条件都是and则or为true
    if (!orModes.length) {
      isMatch = true
    }
    // 匹配判断不通过
    if (!(isMatch && isAndMatch)) {
      return options
    }
    if (String(pro.isAfterDebugger) === 'true') {
      debugger
    }
    // transformRules: [{transformItem: 'url', transform: 'test', transformMatch: 'l5fdq4g69paj'}]
    // cat open/send/reqHeaders/responseText
    // matchItem url/method/async/reqHeaderKey/reqHeaderValue/request/response

    // reqHeaders: this.reqHeaders
    // 规则替换
    let transformRules = pro.transformRules
    transformRules = Array.isArray(transformRules) ? transformRules : []
    transformRules.forEach(rule => {
      const transformItem = rule.transformItem
      // 指定规则匹配
      let b = true
      let transformMatch = rule.transformMatch || ''
      if (transformMatch) {
        String(transformMatch).split(',').forEach(key => {
          if (!ruleMap.get(key)) {
            b = false
          }
        })
      }
      if (!b) {
        return true
      }
      // 规则值类型
      let typer = Object.prototype.toString.call(rule.transform)
      // 打开
      if (/open/.test(cat) && /url|method|async/.test(transformItem)) {
        // 字符串
        if (typer === '[object String]') {
          options[transformItem] = rule.transform
        }
        // 函数
        else if (typer === '[object Function]') {
          try {
            options[transformItem] = rule.transform(options[transformItem], options, rule)
          } catch (e) {
            b = false
          }
        }
      }
      // 发送
      else if (/send/.test(cat) && /request/.test(transformItem)) {
        let payload = options.requestPayload || ''
        let query = options.requestQuery || ''
        if (typeof options.requestPayload === 'object') {
          try {
            payload = JSON.stringify(options.requestPayload)
          } catch (e) {
            payload = ''
          }
        }
        values = [payload, query]
        values = values.map(value => {
          const old = value
          // 字符串
          if (typer === '[object String]') {
            value = rule.transform
          }
          // 函数
          else if (typer === '[object Function]') {
            try {
              value = rule.transform(value, options, rule)
            } catch (e) {
              value = old
            }
          }
          return value
        })
        options.requestPayload = values[0]
        options.requestQuery = values[1]
      }
      // 响应
      else if (/responseText/.test(cat) && /response/.test(transformItem)) {
        let responseText = options.responseText || ''
        const old = responseText
        // 字符串
        if (typer === '[object String]') {
          options[transformItem] = rule.transform
        }
        // 函数
        else if (typer === '[object Function]') {
          try {
            options[transformItem] = rule.transform(responseText, options, rule)
          } catch (e) {
            options[transformItem] = old
          }
        }
      }
      // 请求头
      else if (/reqHeaders/.test(cat) && /reqHeaderKey|reqHeaderValue/.test(transformItem)) {
        let reqHeaders = options.reqHeaders || {}
        let keys = Object.keys(reqHeaders)
        // 头key
        if (transformItem === 'reqHeaderKey') {
          values = keys
        }
        // 头值
        else if (transformItem === 'reqHeaderValue') {
          values = keys.map(key => {
            return reqHeaders[key]
          })
        }
        values = values.map(value => {
          const old = value
          // 字符串
          if (typer === '[object String]') {
            value = rule.transform
          }
          // 函数
          else if (typer === '[object Function]') {
            try {
              value = rule.transform(value, options, rule)
            } catch (e) {
              value = old
            }
          }
          return value
        })
      }
    })
  })
  return options
}

/**
 * @function 是否匹配参数
*/
function isMatchParams (rule) {
  let matchParams = rule?.matchParams || ''
  matchParams = String(matchParams).split(',')
  let b = false
  let href = location.href.toLowerCase()
  matchParams.forEach(item => {
    item = item.toLowerCase()
    if (href.indexOf(item) > -1 && item.trim()) {
      b = true
    }
  })
  return b
}

/**
 * @function 转换打开
*/
function transformOpen (options, serviceType) {
  transformByRules(options, serviceType, 'open')
}

/**
 * @function 转换请求参数
*/
function transformSend (options, serviceType) {
  transformByRules(options, serviceType, 'send')
}

/**
 * @function 转换请求头
*/
function transformReqHeaders (options, serviceType) {
  transformByRules(options, serviceType, 'reqHeaders')
}


/**
 * @function 转换响应
*/
function transformResponseText (options, serviceType) {
  transformByRules(options, serviceType, 'responseText')
}

// 地址转换
apiMonitor.handleAjaxOpen = function (e) {
  let options = e.detail
  transformOpen(options, 'ajax')
}
apiMonitor.handleFetchOpen = function (e) {
  let options = e.detail
  transformOpen(options, 'fetch')
}
apiMonitor.handleScriptSetSrc = function (e) {
  let options = e.detail
  transformOpen(options, 'script')
}

// 请求参数转换
apiMonitor.handleAjaxSend = function (e) {
  let options = e.detail
  transformSend(options, 'ajax')
}
apiMonitor.handleFetchSend = function (e) {
  let options = e.detail
  transformSend(options, 'fetch')
}

// 请求头转换
apiMonitor.handleAjaxSetHeaders = function (e) {
  let options = e.detail
  transformReqHeaders(options, 'ajax')
}
apiMonitor.handleFetchSetHeaders = function (e) {
  let options = e.detail
  transformReqHeaders(options, 'fetch')
}

// 响应文本转换
apiMonitor.handleAjaxResponseText = function (e) {
  let options = e.detail
  transformResponseText(options, 'ajax')
}
apiMonitor.handleFetchResponseText = function (e) {
  let options = e.detail
  transformResponseText(options, 'fetch')
}

// 开启监听
apiMonitor.start()
errorMonitor.start()
performanceMonitor.start()

